"""GitCode API client for fetching PR and Issue information."""

import logging
from datetime import datetime, timedelta
from typing import List, Optional

import requests

from ..models import Issue, PullRequest

logger = logging.getLogger(__name__)


class GitCodeClient:
    """GitCode API client."""

    def __init__(self, api_base_url: str, access_token: str, timeout: int = 30):
        """
        Initialize GitCode API client.

        Args:
            api_base_url: Base URL for GitCode API
            access_token: GitCode access token
            timeout: Request timeout in seconds
        """
        self.api_base_url = api_base_url.rstrip("/")
        self.access_token = access_token
        self.timeout = timeout
        self.session = requests.Session()
        self.session.headers.update({"Accept": "application/json"})

    def _make_request(self, method: str, endpoint: str, **kwargs) -> requests.Response:
        """
        Make HTTP request to GitCode API.

        Args:
            method: HTTP method (GET, POST, etc.)
            endpoint: API endpoint (without base URL)
            **kwargs: Additional arguments for requests

        Returns:
            Response object

        Raises:
            requests.RequestException: If request fails
        """
        url = f"{self.api_base_url}{endpoint}"
        # Extract params from kwargs to avoid duplicate parameter error
        params = kwargs.pop("params", {})
        params["access_token"] = self.access_token

        try:
            response = self.session.request(
                method=method, url=url, params=params, timeout=self.timeout, **kwargs
            )
            response.raise_for_status()
            return response
        except requests.RequestException as e:
            logger.error(f"GitCode API request failed: {method} {endpoint} - {e}")
            raise

    def get_pulls(
        self, repo: str, state: str = "opened", per_page: int = 100, page: int = 1
    ) -> List[PullRequest]:
        """
        Get list of pull requests for a repository.

        Args:
            repo: Repository name in format 'org/repo'
            state: PR state (opened, closed, all)
            per_page: Number of results per page
            page: Page number

        Returns:
            List of PullRequest objects
        """
        endpoint = f"/api/v5/repos/{repo}/pulls"
        params = {"state": state, "per_page": per_page, "page": page}

        response = self._make_request("GET", endpoint, params=params)
        data = response.json()

        if not isinstance(data, list):
            logger.warning(f"Unexpected response format for get_pulls: {type(data)}")
            return []

        pulls = [PullRequest.from_dict(pr_data) for pr_data in data]
        logger.info(f"Fetched {len(pulls)} pull requests from {repo} (state={state})")
        return pulls

    def get_pull_detail(self, repo: str, pr_number: int) -> Optional[PullRequest]:
        """
        Get detailed information about a specific pull request.

        Args:
            repo: Repository name in format 'org/repo'
            pr_number: Pull request number

        Returns:
            PullRequest object or None if not found
        """
        endpoint = f"/api/v5/repos/{repo}/pulls/{pr_number}"

        try:
            response = self._make_request("GET", endpoint)
            data = response.json()
            return PullRequest.from_dict(data)
        except requests.RequestException as e:
            logger.error(f"Failed to get PR detail: {repo}#{pr_number} - {e}")
            return None

    def get_pull_issues(self, repo: str, pr_number: int) -> List[Issue]:
        """
        Get issues associated with a pull request.

        Args:
            repo: Repository name in format 'org/repo'
            pr_number: Pull request number

        Returns:
            List of Issue objects
        """
        endpoint = f"/api/v5/repos/{repo}/pulls/{pr_number}/issues"

        try:
            response = self._make_request("GET", endpoint)
            data = response.json()

            if not isinstance(data, list):
                logger.warning(f"Unexpected response format for get_pull_issues: {type(data)}")
                return []

            issues = [Issue.from_dict(issue_data) for issue_data in data]
            logger.info(f"Fetched {len(issues)} issues for PR {repo}#{pr_number}")
            return issues
        except requests.RequestException as e:
            logger.error(f"Failed to get PR issues: {repo}#{pr_number} - {e}")
            return []

    def filter_today_pulls(self, pulls: List[PullRequest]) -> List[PullRequest]:
        """
        Filter pull requests created today.

        Args:
            pulls: List of PullRequest objects

        Returns:
            List of PullRequest objects created today
        """
        today = datetime.now().date()
        today_pulls = [pr for pr in pulls if pr.created_at.date() == today]
        logger.info(f"Filtered {len(today_pulls)} PRs created today from {len(pulls)} total PRs")
        return today_pulls

    def filter_pulls_by_date(
        self, pulls: List[PullRequest], target_date: datetime.date
    ) -> List[PullRequest]:
        """
        Filter pull requests created on a specific date.

        Args:
            pulls: List of PullRequest objects
            target_date: Target date to filter by

        Returns:
            List of PullRequest objects created on the target date
        """
        filtered_pulls = [pr for pr in pulls if pr.created_at.date() == target_date]
        logger.info(
            f"Filtered {len(filtered_pulls)} PRs created on {target_date} from {len(pulls)} total PRs"
        )
        return filtered_pulls

    def filter_recent_pulls(
        self, pulls: List[PullRequest], days: int = 1
    ) -> List[PullRequest]:
        """
        Filter pull requests created within specified days.

        Args:
            pulls: List of PullRequest objects
            days: Number of days to look back

        Returns:
            List of PullRequest objects created within specified days
        """
        cutoff_date = datetime.now().date() - timedelta(days=days)
        recent_pulls = [pr for pr in pulls if pr.created_at.date() >= cutoff_date]
        logger.info(
            f"Filtered {len(recent_pulls)} PRs created in last {days} days from {len(pulls)} total PRs"
        )
        return recent_pulls

